<?php

namespace app\common\controller;


use app\lib\exception\ParamException;
use app\api\controller\v1\Token;
use think\Db;

class JuliangService extends Base
{
    protected $account;
    protected $access_token;
    protected $start_date;
    protected $end_date;

    /**
     * 记录系统日志
     * @param string $behavior
     * @param array $arr
     */
    public function RecordSystemLog($uid,$behavior,$description)
    {
        $data['uid'] = $uid;
        $data['ip'] = $this->request->ip();
        $data['behavior'] = $behavior;
        $data['description'] = $description;
        model('SystemLog')->writeSystemLog($data);  // 日志入库
    }

    /**
     * 获取报告
     */
    public function getReportData($acc_id, $yesterday=0)
    {
        $account = Db::name('account')->find($acc_id);

        if($account['syn_status'] != 1){
            throw new ParamException(['msg'=>'账户未开启同步','errorCode'=>10001]);
        }
        if($account['syn_num'] == 0){
            $startDate= date('Y-m-d', strtotime('-1 month'));
        }else{
            if($yesterday){
                $startDate= date('Y-m-d', strtotime('-1 days'));
            }else{
                $startDate= date('Y-m-d');
            }
        }
        $endDate = date('Y-m-d');

        $this->start_date = $startDate;
        $this->end_date = $endDate;

        $access_token = $this->getAccessToken($account);
        if(!$access_token){
            model('Account')->save(['syn_status'=>2],['id'=>$acc_id]);
            throw new ParamException(['msg'=>'未获取到access_token','errorCode'=>20001]);
        }

        $this->access_token = $access_token;
        $this->account = $account;

        $this->getAdvertiserData();
        $this->getCampaignData();
        $this->getAdData();
        $this->getCreativeData();

        Db::name('account')->where('id', $acc_id)->setInc('syn_num'); // 同步数加1
        return json(['code' => 1001, 'msg' => '未定义消息']);
    }

    public function getAccessToken($account)
    {
        $token_list = Db::name('access_token')->where(['admin_id'=>$account['admin_id'],'channel_id'=>3])->select();

        $access_token = '';
        foreach ($token_list as $k=>$v){
            $advertiser_ids = json_decode($v['advertiser_ids'], true);
            if(in_array($account['macc_id'],$advertiser_ids)){
                if($v['expires_time'] <= time()){
                    // 刷新access_token
                    $access_token = (new Token())->getJuLiangRefreshToken($v['refresh_token'],$account['admin_id'],$v['advertiser_ids']);
                }else{
                    $access_token = $v['access_token'];
                }
            }
        }

        return $access_token;
    }


    // 广告主数据
    public function getAdvertiserData()
    {
        $url = 'https://ad.oceanengine.com/open_api/2/report/advertiser/get/';

        $args = [];

        $list = $this->joinParam($url,$args);

        if($list){
            foreach ($list as $k=>$v){
                $this->saveReport($v);
            }
        }else{
            $this->RecordSystemLog($this->account['admin_id'],'manage/JuliangService/getAdvertiserData','未获取到巨量广告主数据');
        }

    }


    // 广告组数据
    public function getCampaignData()
    {
        $url = 'https://ad.oceanengine.com/open_api/2/report/campaign/get/';

        $args = [];

        $list = $this->joinParam($url,$args);

        if($list){
            foreach ($list as $k=>$v){
                $append = [
                    'campaign_id' => $v['campaign_id'],
                    'campaign_name' => $v['campaign_name']
                ];
                $this->saveReport($v, $append);
            }
        }else{
            $this->RecordSystemLog($this->account['admin_id'],'manage/JuliangService/getCampaignData','未获取到巨量广告组数据');
        }
    }

    // 广告计划数据
    public function getAdData()
    {
        $url = 'https://ad.oceanengine.com/open_api/2/report/ad/get/';

        $args = [];

        $list = $this->joinParam($url,$args);

        if($list){
            foreach ($list as $k=>$v){
                $append = [
                    'campaign_id' => $v['campaign_id'],
                    'campaign_name' => $v['campaign_name'],
                    'ad_id' => $v['ad_id'],
                    'ad_name' => $v['ad_name']
                ];
                $this->saveReport($v,$append);
            }
        }else{
            $this->RecordSystemLog($this->account['admin_id'],'manage/JuliangService/getAdData','未获取到巨量广告计划数据');
        }
    }

    // 广告创意数据
    public function getCreativeData()
    {
        $url = 'https://ad.oceanengine.com/open_api/2/report/creative/get/';

        $args = [];

        $list = $this->joinParam($url,$args);

        if($list){
            foreach ($list as $k=>$v){
                $append = [
                    'campaign_id' => $v['campaign_id'],
                    'campaign_name' => $v['campaign_name'],
                    'ad_id' => $v['ad_id'],
                    'ad_name' => $v['ad_name'],
                    'creative_id' => $v['creative_id'],
                ];
                $this->saveReport($v,$append);
            }
        }else{
            $this->RecordSystemLog($this->account['admin_id'],'manage/JuliangService/getCreativeData','未获取到巨量广告创意数据');
        }
    }

    // 获取第三方落地页站点列表
    public function getThirdSiteData($account)
    {
        $url = 'https://ad.oceanengine.com/open_api/2/tools/third_site/get/';

        $args = [
            'advertiser_id' => $account['adv_id'],
            'page' => 1,
            'page_size' => 100,
        ];

        foreach ($args as $key => $value) {
            $args[$key] = is_string($value) ? $value : json_encode($value);
        }

        $url = $url . "?" . http_build_query($args);
        $access_token = $this->getAccessToken($account);
        $res_json = curl_get($url,$access_token);
        $res = json_decode($res_json, true);
        if($res['code'] == 0){
            return $res['data']['list'];
        }else{
            trace($res_json,'error');
            throw new ParamException(['msg'=>$res['message'] ?? '落地页同步失败','errorCode'=>30005]);
        }
    }

    // 获取橙子建站站点详细信息
    public function getSiteData($account)
    {
        $url = 'https://ad.oceanengine.com/open_api/2/tools/site/get/';

        $args = [
            'advertiser_id' => $account['adv_id'],
            'page' => 1,
            'page_size' => 100,
        ];

        foreach ($args as $key => $value) {
            $args[$key] = is_string($value) ? $value : json_encode($value);
        }

        $url = $url . "?" . http_build_query($args);
        $access_token = $this->getAccessToken($account);
        $res_json = curl_get($url,$access_token);
        $res = json_decode($res_json, true);
        if($res['code'] == 0){
            $list = $res['data']['list'];
            foreach ($list as $k=>$v){
                $list[$k]['url'] = $this->getSitePreviewData($account['adv_id'], $v['siteId'],$access_token);
            }
            return $list;
        }else{
            trace($res_json,'error');
            throw new ParamException(['msg'=>$res['message'] ?? '落地页同步失败','errorCode'=>30006]);
        }
    }

    // 获取橙子建站站点预览地址
    public function getSitePreviewData($advertiser_id,$site_id,$access_token)
    {
        $url = 'https://ad.oceanengine.com/open_api/2/tools/site/preview/';

        $args = [
            'advertiser_id' => $advertiser_id,
            'site_id' => $site_id
        ];

        foreach ($args as $key => $value) {
            $args[$key] = is_string($value) ? $value : json_encode($value);
        }

        $url = $url . "?" . http_build_query($args);

        $res_json = curl_get($url,$access_token);
        $res = json_decode($res_json, true);
        if($res['code'] == 0){
            return $res['data']['url'];
        }else{
            trace($res_json,'error');
            throw new ParamException(['msg'=>$res['message'] ?? '获取橙子建站站点预览地址失败','errorCode'=>30007]);
        }
    }

    public function saveReport($v,$append=[])
    {
        $param['date'] = date('Y-m-d',strtotime($v['stat_datetime']));
        $param['adv_id'] = $this->account['adv_id'];
        $param['acc_name'] = $this->account['acc_name'];
        $param['impression'] = $v['show'];
        $param['click'] = $v['click'];
        $param['cost'] = $v['cost'];
        $param['ctr'] = $v['ctr'];
        $param['cpc'] = $v['avg_click_cost'];
        $param['cpm'] = $v['avg_show_cost'];
        $param['convert_num'] = $v['convert'];
        $param['convert_cost'] = $v['convert_cost'];
        $param['convert_rate'] = $v['convert_rate'];
        $where = [
            'date'=>date('Y-m-d',strtotime($v['stat_datetime'])),
            'adv_id'=>$this->account['adv_id'],
            'campaign_id'=>$append['campaign_id'] ?? 0,
            'ad_id'=>$append['ad_id'] ?? 0,
            'creative_id'=>$append['creative_id'] ?? 0,
        ];
        $param['admin_id'] = $this->account['admin_id'];
        $param['create_time'] = time();
        $param['update_time'] = time();

        $param = array_merge($param, $append);

        if($this->account['syn_num'] == 0){
            $res_db = Db::name('juliang_report')->insert($param);
            if(!$res_db){
                trace($param,'error');
            }
        }else{
            $one = model('JuliangReport')->where($where)->find();
            if($one){
                model('JuliangReport')->where('id',$one['id'])->delete();
            }
            $res_db = Db::name('juliang_report')->insert($param);
            if(!$res_db){
                trace($param,'error');
            }
        }
    }

    // 拼接参数，发送请求
    public function joinParam($url, $params)
    {
        $args = [
            'advertiser_id' => $this->account['adv_id'],
            'start_date' => $this->start_date,
            'end_date' => $this->end_date,
            'group_by' => ["STAT_GROUP_BY_FIELD_ID", "STAT_GROUP_BY_FIELD_STAT_TIME"],
            'fields' => ['cost','show','avg_show_cost','avg_click_cost','click','ctr','convert','convert_cost','convert_rate'],
            'page' => 1,
            'page_size' => 1000,
        ];

        $args = array_merge($args, $params);

        foreach ($args as $key => $value) {
            $args[$key] = is_string($value) ? $value : json_encode($value);
        }

        $url = $url . "?" . http_build_query($args);

        $res = curl_get($url,$this->access_token);

        $result = json_decode($res, true);

        if($result['code'] == 0){
            $list = $result['data']['list'] ?? [];
            if($list){
                return $list;
            }else{
                model('Account')->save(['syn_status'=>2],['id'=>$this->account['id']]);
                throw new ParamException(['msg'=>'渠道账户没有数据','errorCode'=>10002]);
            }
        }else{
            model('Account')->save(['syn_status'=>2],['id'=>$this->account['id']]);
            throw new ParamException(['msg'=>$result['message'],'errorCode'=>20002]);
        }
    }

}